www.gusucode.com > VC++ ASP文件上传组件源代码+调用示例-源码程序 > VC++ ASP文件上传组件源代码+调用示例-源码程序/code/aspup_src/MyRequest/Form.cpp

    //Download by http://www.NewXing.com
// Form.cpp : Implementation of CForm
#include "stdafx.h"
#include "MyRequest.h"
#include "Parser.h"
#include "Form.h"

#include <string>
using namespace std;


/////////////////////////////////////////////////////////////////////////////
// CForm

CForm::CForm()
{
	m_bOnStartPageCalled = FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// ISupportsErrorInfo interface implementation

STDMETHODIMP CForm::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_IForm
	};
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// IForm interface implementation

STDMETHODIMP CForm::OnStartPage(IUnknown* pUnk)
{
	if(!pUnk)
		return E_POINTER;

	CComQIPtr<IScriptingContext, &IID_IScriptingContext> spContext(pUnk);
	
	if(!spContext) 
		return E_NOINTERFACE;
	
	// Get Request Object Pointer
	HRESULT hr = spContext->get_Request(&m_piRequest);
	if(FAILED(hr))
		return hr;

	// Get Response Object Pointer
	hr = spContext->get_Response(&m_piResponse);
	if(FAILED(hr))
		return hr;

	m_bOnStartPageCalled = TRUE;

	return S_OK;
}

STDMETHODIMP CForm::OnEndPage()  
{
	m_bOnStartPageCalled = FALSE;
	m_piRequest.Release();
	m_piResponse.Release();
	return S_OK;
}

STDMETHODIMP CForm::Init(VARIANT varBinary)
{
	CComVariant vtBinary = varBinary;
	HRESULT hr = S_OK;

	// ** if varBinary is not been supplied
	if(vtBinary.vt == VT_ERROR) {
		if(m_piRequest == NULL) return ::Error(_T("Form.Init()"), _T("Object has not initialized correctly"), IID_IForm, E_POINTER);

		long lSize;
		m_piRequest->get_TotalBytes(&lSize);

		CComVariant vtSize = lSize;

		// ** read from ASP Request Object
		m_piRequest->BinaryRead(&vtSize, &vtBinary);
	}

	BOOL bValid = GetRequestMethod() == _T("POST");
	if(!bValid)	return ::Error(_T("Form.Init()"), _T("method must be set to 'POST'"), IID_IForm);

	bValid = GetContentType() == _T("multipart/form-data");
	if(!bValid)	return ::Error(_T("Form.Init()"), _T("encoding type must be set to 'multipart/form-data'"), IID_IForm);

	// ** Should be safe array containing variants
	if(vtBinary.vt != (VT_UI1|VT_ARRAY))
		return ::Error(_T("Form.Init()"), _T("Input type was not expected"), IID_IForm);

	SAFEARRAY* pSafeArray = (SAFEARRAY*)(vtBinary.pparray);

	CComBSTR bstr = GetBoundry();

	int cbMultiByte = ::WideCharToMultiByte(CP_ACP, 0, bstr, -1, NULL, 0, NULL, NULL);
	LPSTR lpMultiByteStr = new char[cbMultiByte+2];
	::WideCharToMultiByte(CP_ACP, 0, bstr, -1, lpMultiByteStr, cbMultiByte, NULL, NULL);
	CBuffer bBoundry(lpMultiByteStr);

	// ** Get a pointer to the elements of the array.
	LPBYTE HUGEP lpData;
	SafeArrayAccessData(pSafeArray, (void HUGEP* FAR*)&lpData);

	long lLBound, lUBound;
	// ** One dimensional array. Get the bounds for the array.
	SafeArrayGetLBound(pSafeArray, 1, &lLBound);
	SafeArrayGetUBound(pSafeArray, 1, &lUBound);

	// ** Get the count of elements
	long lDataSize = lUBound-lLBound + 1;

	CBuffer bRequest(lpData, lDataSize);

	CParser p(bRequest, bBoundry);
	hr = p.Parse(this);
	if(FAILED(hr)) return ::Error(_T("Form.Init()"), _T("object has encountered an error during parsing"), IID_IForm, hr);

	delete[] lpMultiByteStr;

	// ** Decrement the access count for the array.
	SafeArrayUnaccessData(pSafeArray);
	return S_OK;
}

STDMETHODIMP CForm::get_Count(long* plCount)
{
	if(plCount == NULL) return E_POINTER;
	*plCount = m_vecItems.size();
	return S_OK;
}

STDMETHODIMP CForm::get_Item(VARIANT Index, IListItem** ppItem)
{
	if(ppItem == NULL) return E_POINTER;

	if(Index.vt != VT_BSTR) {
		CComVariant vtIndex(Index);
		HRESULT hr = vtIndex.ChangeType(VT_I4);
		if(FAILED(hr)) return ::Error(_T("Form.Item()"), _T("input type is not expected"), IID_IForm, hr);

		long lIndex = vtIndex.lVal;

		if(lIndex < 1 || lIndex > m_vecItems.size())
			return ::Error(_T("Form.Item()"), _T("index is out of range"), IID_IForm, E_INVALIDARG);

		// ** Get the item
		CComObject<CListItem>* pListItem = m_vecItems[lIndex-1];
		hr = pListItem->QueryInterface(IID_IListItem, (void **)ppItem);
		if(FAILED(hr))	return E_UNEXPECTED;
		return S_OK;
	}

	CComBSTR bstrName = Index.bstrVal;
	bstrName.ToLower();

	for(int i = 0; i < m_vecItems.size(); i++) {
		CComObject<CListItem>* pListItem = m_vecItems[i];
		CComBSTR bstrItemName = pListItem->GetName();
		bstrItemName.ToLower();
		if(bstrName == bstrItemName) {
			HRESULT hr = pListItem->QueryInterface(IID_IListItem, (void **)ppItem);
			if(FAILED(hr))	return E_UNEXPECTED;
			return S_OK;
		}
	}

	return ::Error(_T("Form.Item()"), _T("index key is not valid"), IID_IForm, E_INVALIDARG);
}

STDMETHODIMP CForm::get__NewEnum(IUnknown** ppUnk)
{
	if(ppUnk == NULL)
		return E_POINTER;

	typedef CComEnum<IEnumVARIANT, &IID_IEnumVARIANT,
					VARIANT, _Copy<VARIANT> > ComVarEnum;
	
	typedef CComObject<ComVarEnum> VariantEnum;

	VariantEnum* pEnum = NULL;
	HRESULT hr = VariantEnum::CreateInstance(&pEnum);
	if(FAILED(hr)) return hr;

	std::vector< CComVariant > vecItems;
	for(int i = 0; i < m_vecItems.size(); i++) {
		// ** Get the item
		CComObject<CListItem>* pItem = m_vecItems[i];
		IDispatch* pDispatch;
		pItem->QueryInterface(IID_IDispatch, (void **)&pDispatch);
		vecItems.push_back(CComVariant(pDispatch));
		pDispatch->Release();
	}

	hr = pEnum->Init(vecItems.begin(), 
					vecItems.end(), 
					0, AtlFlagCopy);
	
	if(FAILED(hr)) return hr;

	hr = pEnum->QueryInterface(IID_IEnumVARIANT, (void**) ppUnk);

	if(FAILED(hr)) return hr;

	return S_OK;
}


CComObject<CListItem>* CForm::GetItem(const CComBSTR& bstrName) {
	CComBSTR bstrTemp = bstrName;
	bstrTemp.ToLower();

	CComObject<CListItem>* pListItem = NULL;
	for(int i = 0; i < m_vecItems.size(); i++) {
		pListItem = m_vecItems[i];
		CComBSTR bstrItemName = pListItem->GetName();
		bstrItemName.ToLower();
		if(bstrTemp == bstrItemName) {
			return pListItem;
		}
	}

	return NULL;
}

void CForm::AddItem(CComBSTR bstrName, CComBSTR bstrFileName, CComBSTR bstrCType, CBuffer bContent, BOOL bFile)
{
	CComObject<CListItem>* pListItem = GetItem(bstrName);
	if(pListItem == NULL) {
		HRESULT hr = CComObject<CListItem>::CreateInstance(&pListItem);
		pListItem->AddRef();
		pListItem->SetName(bstrName);
		m_vecItems.push_back(pListItem);
	}

	pListItem->AddItem(bstrFileName, bstrCType, bContent, bFile);
}

void CForm::FinalRelease()
{
	m_vecItems.erase(m_vecItems.begin(), m_vecItems.end());
}

CComBSTR CForm::GetRequestMethod()
{
	CComPtr<IRequestDictionary> piServerVariables;
	m_piRequest->get_ServerVariables(&piServerVariables);

	IRequestDictionary* pServerVariablesDictionary;
	m_piRequest->get_ServerVariables(&pServerVariablesDictionary);

	CComVariant vtItemName(_T("REQUEST_METHOD"));
	CComVariant vtRequestMethod;
	piServerVariables->get_Item(vtItemName, &vtRequestMethod);

	vtRequestMethod.ChangeType(VT_BSTR);

	CComBSTR bstrRequestMethod = vtRequestMethod.bstrVal;
	bstrRequestMethod.ToUpper();

	return bstrRequestMethod;
}

CComBSTR CForm::GetContentType()
{
	CComPtr<IRequestDictionary> piServerVariables;
	m_piRequest->get_ServerVariables(&piServerVariables);

	CComVariant vtItemName(_T("HTTP_CONTENT_TYPE"));
	CComVariant vtContentType;
	piServerVariables->get_Item(vtItemName, &vtContentType);

	vtContentType.ChangeType(VT_BSTR);

	CComBSTR bstrTemp(vtContentType.bstrVal);
	bstrTemp.ToLower();
	wstring wstr = bstrTemp;

	int i = wstr.find(L"multipart/form-data;");
	if(i == -1) return _T("");
	else return _T("multipart/form-data");
}

CComBSTR CForm::GetBoundry()
{
	CComPtr<IRequestDictionary> piServerVariables;
	m_piRequest->get_ServerVariables(&piServerVariables);

	CComVariant vtItemName(_T("HTTP_CONTENT_TYPE"));
	CComVariant vtContentType;
	piServerVariables->get_Item(vtItemName, &vtContentType);

	vtContentType.ChangeType(VT_BSTR);

	CComBSTR bstrTemp(vtContentType.bstrVal);
	bstrTemp.ToLower();
	wstring wstr = bstrTemp;

	int i = wstr.find(L"boundary=");
	if(i == -1) return _T("");
	wstring wstrResult = wstr.substr(i+9);
	CComBSTR bstr(wstrResult.c_str());
	return bstr;
}